'''PyQt4 的日历笔记脚本,显示日历,并允许在任意一个日期添加笔记,保存.
展示了QCalendarWidget(日历),QTableWidget(表格),QTableWidgetItem(表格单元)
以及相关一些组件的用法.

选择日历的日子,然后添加笔记的脚本.有笔记的日子文字格式与没有笔记的日子不同,
笔记按{'年-月(不补零)':{'日(不补零)':笔记}}格式保存在eventData.json中,若笔记
为空字符串,则取消该日子的笔记标志

注意!要选择了当月的日子才会更新当月的数据.

@2019-12-31 by setycyas
'''

import sys
import os
import json
from datetime import date, datetime

from PyQt4 import QtCore, QtGui

import MyCalendarNote_ui

class MainWindow(QtGui.QMainWindow):

  def __init__(self):
    ## 设置窗体
    super(MainWindow,self).__init__()
    self.ui = MyCalendarNote_ui.Ui_MainWindow()
    self.ui.setupUi(self)
    ## 变量
    ## 有事件的日子的字体
    self.qEventFormat = QtGui.QTextCharFormat()
    self.qEventFormat.setFontItalic(True) # 斜体
    self.qEventFormat.setUnderlineStyle(1) # 实线下划线
    self.qEventFormat.setFontPointSize(20) # 变大
    ## 无事件的日子的字体,默认即可
    self.qDefaultFormat = QtGui.QTextCharFormat()
    ## 表格单元数组,共31个,表示1-31日的笔记.数组以None开头,这样第一个单元
    ## 的index就是1,比较简单
    self.items = [None]
    self.ui.tableWidget.setRowCount(10)
    self.ui.tableWidget.setColumnCount(4)
    for i in range(31):
      item = QtGui.QTableWidgetItem(str(i+1)+'u')
      self.ui.tableWidget.setItem(i%10, i//10, item)
      self.items.append(item)
    ## 笔记字典以及文件,格式为{'年-月(不补零)':{'日(不补零)':笔记}}
    ## 尝试读取,读取失败则新建
    self.dataFilePath = sys.path[0]+r'\eventData.json'
    try:
      with open(self.dataFilePath, 'r') as f:
        self.eventData = json.load(f)
      self.ui.statusbar.showMessage('成功读取日志!')
    except:
      self.eventData = {}
      self.ui.statusbar.showMessage('读取日志失败!新建日志')
    ## 绑定各种事件响应
    QtCore.QObject.connect(self.ui.pushButton,QtCore.SIGNAL("clicked()"),self.save)
    QtCore.QObject.connect(self.ui.calendarWidget,QtCore.SIGNAL("selectionChanged()"),self.onSelected)
    ## 刷新显示
    self.reFresh()
    return
  
  ## 保存笔记
  def save(self):
    curYear, curMonth, curDay, ymString = self._getSelection()
    if (not (ymString in self.eventData)):
      self.eventData[ymString] = {}
    text = self.ui.plainTextEdit.toPlainText().strip()
    self.eventData[ymString][curDay] = text
    if (len(text) == 0):
      del self.eventData[ymString][curDay]
    try:
      with open(self.dataFilePath, 'w') as f:
        json.dump(self.eventData, f)
        self.ui.statusbar.showMessage('保存笔记成功!')
    except:
      self.ui.statusbar.showMessage('保存笔记失败!')
    self.reFresh()
    return
  
  ## 选择新日期
  def onSelected(self):
    urYear, curMonth, curDay, ymString = self._getSelection()
    self.ui.statusbar.showMessage(ymString+'-'+curDay)
    self.reFresh()
    return
  
  ## 刷新各种显示
  def reFresh(self):
    curYear, curMonth, curDay, ymString = self._getSelection()
    ## 重置预览单元和日历上的事件显示
    for i in range(1, 31+1):
      day = str(i)
      ## 日子是否合法,不合法则没有笔记
      isLegalDay = True
      try:
        _date = datetime.strptime(ymString+'-'+day, '%Y-%m-%d')
      except:
        isLegalDay = False
      ## 按是否合法处理
      if isLegalDay:
        if ((ymString in self.eventData) and 
          (day in self.eventData[ymString])):
          self.items[i].setText(self.eventData[ymString][day])
          self.ui.calendarWidget.setDateTextFormat(_date, self.qEventFormat)
        else:
          self.items[i].setText('')
          self.ui.calendarWidget.setDateTextFormat(_date, self.qDefaultFormat)
      else:
        self.items[i].setText('')
    ## 重置当日事件文本框
    if ((ymString in self.eventData) and 
      (curDay in self.eventData[ymString])):
      self.ui.plainTextEdit.setPlainText(self.eventData[ymString][curDay])
    else:
      self.ui.plainTextEdit.setPlainText("这里输入笔记")  
    return
    
  ## 获取当前选择日期,返回一个4元列表,都是字符串,不补零:
  ## ['年','月','日','年-月'],最后的'年-月'在读取资料时有用,是一个key
  def _getSelection(self):
    curYear = str(self.ui.calendarWidget.selectedDate().year())
    curMonth = str(self.ui.calendarWidget.selectedDate().month())
    curDay = str(self.ui.calendarWidget.selectedDate().day())   
    ymString = curYear+'-'+curMonth
    result = [curYear, curMonth, curDay, ymString]
    return result


## 开始运行    
if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  window= MainWindow()
  window.show()
  app.exec_()
  